# _*_ coding:UTF-8 _*_
__author__ = 'shede333'

import hashlib
import os
import shelve
import sys

g_config_file_name = ".config"  # 配置文件的文件名,放在当前目录(脚本文件)下


def test(test_str=""):
    print("This is Module, work fine!, in: ", os.path.split(sys.argv[0])[1])
    print(__file__)
    if len(test_str) > 0:
        print(test_str)


def please_user_input(prompt="please input:", is_force=False, func_confirm=None):
    user_input = input(prompt)
    if is_force and ((user_input is None) or (len(user_input) <= 0)):
        user_input = please_user_input(prompt=prompt, is_force=is_force)
    elif func_confirm is not None:
        try:
            is_confirm = func_confirm(user_input)
        except Exception:
            print("参数func_confirm设置错误，它是带有一个参数的函数")
            is_confirm = True  # func_confirm have problem
        if not is_confirm:
            user_input = please_user_input(prompt=prompt, is_force=is_force,
                                           func_confirm=func_confirm)
    return user_input


def user_input_path(prompt="please input path:", is_dir=False):
    """
    命令行内提示用户输入 路径（输入错入则会循环提示输入正确内容）
    :param prompt: 提示信息，默认"please input path:"
    :param is_dir: 路径是否为目录，默认False
    :return: 文件/目录路径
    """
    user_input = input(prompt)
    user_input = os.path.expanduser(user_input)
    if is_dir:
        if os.path.isdir(user_input):
            return user_input
        else:
            print("path is not directory:", user_input)
            return user_input_path(prompt, is_dir=is_dir)
    else:
        if os.path.exists(user_input):
            return user_input
        else:
            print("path is not exist:", user_input)
        return user_input_path(prompt, is_dir=is_dir)


def user_input_bool(prompt="please input [yes] or [no]:"):
    """
    命令行内提示用户输入 布尔值，输入y/n开头的字符串即可（输入错入则会循环提示输入正确内容）
    :param prompt: 提示信息，默认"please input [yes] or [no]:"
    :return: 布尔值
    """
    user_input = input(prompt)
    if user_input.startswith("y"):
        return True
    elif user_input.startswith("n"):
        return False
    else:
        return user_input_bool("input error, input [yes] or [no]:")


def file_md5(file_path):
    """
    计算文件的MD5
    :param file_path: 文件路径
    :return: 文件md5
    """
    if not os.path.isfile(file_path):
        return
    tmp_file = open(file_path, "rb")
    m1 = hashlib.md5(tmp_file.read()).hexdigest()
    tmp_file.close()
    return m1


def file_list_in_dir(dir_path, is_recursion=True, ext_names=(), exclude_dirs=(), has_hidden=False):
    """
    获取目录里所有的文件信息
    :param dir_path: 目录路径
    :param is_recursion: 是否递归遍历子目录，默认True
    :param ext_names: 扩展名列表，以此过滤出需要的文件，例如(".h", ".m")
    :param exclude_dirs: 需要排除的目录（黑名单）
    :param has_hidden: 是否包含隐藏文件/目录，默认False
    :return: 返回文件列表，内含(file_name, file_path)
    """
    if not os.path.isdir(dir_path):
        return []
    files = []
    ext_name_set = set(ext_names)
    exclude_dirs_set = set(exclude_dirs)
    tmp_file_list = os.listdir(dir_path)
    for file_name in tmp_file_list:
        if (not has_hidden) and file_name.startswith("."):
            continue
        tmp_path = os.path.join(dir_path, file_name)
        if os.path.isfile(tmp_path):
            tmp_ext = os.path.splitext(file_name)[1]
            if tmp_ext not in ext_name_set:
                continue
            files.append((file_name, tmp_path))
        elif is_recursion and os.path.isdir(tmp_path):
            if tmp_path in exclude_dirs_set:
                continue
            tmp_list = file_list_in_dir(tmp_path, is_recursion, ext_names, exclude_dirs, has_hidden)
            files.extend(tmp_list)
    return files


def list_convert_to_dic(origin_list, dic_default_value=1):
    tmp_dic = {}
    for tmp_element in origin_list:
        tmp_dic[tmp_element] = dic_default_value
    return tmp_dic


def get_file_dir(file__):
    """
    获取"__file__"所在的目录
    :param file__: "__file__"对象
    :return: 目录路径
    """
    return os.path.abspath(os.path.dirname(file__))


def get_root_dir():
    """
    获取程序运行的根目录
    :return: 目录路径
    """
    return (os.path.split(os.path.abspath(sys.argv[0])))[0]


def load_config(config_path=None):
    params = {}
    if config_path is None:
        config_path = os.path.join(get_root_dir(), g_config_file_name)
    config_params = shelve.open(config_path)
    try:
        for tmp_key in config_params.keys():
            params[tmp_key] = config_params[tmp_key]
    finally:
        config_params.close()
    return params


def save_config(params, config_path=None):
    if config_path is None:
        config_path = os.path.join(get_root_dir(), g_config_file_name)
    config_params = shelve.open(config_path)
    try:
        for tmp_key in params:
            config_params[tmp_key] = params[tmp_key]
    finally:
        config_params.close()


def print_list(tmp_list, prefix_str=""):
    for element in tmp_list:
        print(prefix_str, element)


def print_dic(tmp_dic, prefix_str=""):
    for tmp_key in tmp_dic:
        print(prefix_str, tmp_key, " : ", tmp_dic[tmp_key])


def get_value_from_config(key_name=None, prompt=None, func_confirm=None):
    final_value = None
    config_file_path = os.path.join(get_root_dir(), g_config_file_name)
    config_dic = load_config(config_file_path)
    if key_name is None:
        # 使用默认值，默认值为当前执行的主脚本路径的md5值
        tmp_value = os.path.abspath(sys.argv[0])
        key_name = hashlib.md5(tmp_value).hexdigest()
    if key_name in config_dic:
        tmp_value = config_dic[key_name]
        print("是否使用已存储的值： %s : %s " % (key_name, tmp_value))
        if user_input_bool():  # 询问用户是否使用这个值
            final_value = tmp_value

    if final_value is None:
        if prompt is None:
            user_input_value = please_user_input(is_force=True, func_confirm=func_confirm)
        else:
            user_input_value = please_user_input(prompt=prompt, is_force=True,
                                                 func_confirm=func_confirm)

        if user_input_value is not None:
            save_config(config_file_path, {key_name: user_input_value})
            final_value = user_input_value

    return final_value


def main():
    sys.exit()
    config_path = os.path.join(get_root_dir(), g_config_file_name)
    print(config_path)
    print("config1:", load_config())
    save_config(params={"k3": "vsdhk", "hello": "world"})
    print("config2:", load_config(config_path))
    sys.exit()
    dir_path = "/Volumes/Mac/iphone-pub"
    print("file_list_in_dir: ", len(file_list_in_dir(dir_path, is_recursion=True)))
    # print("file_list_recursion_dir: ", len(file_list_recursion_dir(dir_path)))


if __name__ == '__main__':
    main()
